#include "mythread.hpp"
#include "block_queue.hpp"
#include "task.hpp"
#include <string>
#include <unistd.h>
#include <ctime>
#include <vector>

using namespace my_thread;
using block_queue_t = BlockQueue<Task>;

#define PRODUCTER_NUM 1
#define CONSUMER_NUM 1

class ThreadDate
{
public:
    ThreadDate(const std::string& thread_name, block_queue_t& bq)
    : _thread_name(thread_name), _bq(bq)
    {}

    std::string _thread_name;
    block_queue_t& _bq;
};

void product(ThreadDate &thread_data)
{
    sleep(3);
    //int data = 0;
    srand((unsigned int)time(nullptr));
    while (1)
    {
        int x = rand() % 100 + 1;
        int y = rand() % 100 + 1;
        Task task(x, y);

        std::cout << thread_data._thread_name << ": ";
        task.question();
        //std::cout << thread_data._thread_name <<" 生产数据：" << data << std::endl;
        thread_data._bq.push(task);
        //data++;

        sleep(1);
    }
    
}
void consum(ThreadDate &thread_data)
{
    //int data;
    Task task(0, 0);
    while (1)
    {
        //sleep(1);
        thread_data._bq.pop(&task);
        std::cout << thread_data._thread_name << ": ";
        task.show_result();
    }
    
}

void createThread(func_t<ThreadDate> func, std::vector<mythread<ThreadDate>> &threads, int threadNum, block_queue_t &bq, const char *name)
{
    for (int i = 0; i < threadNum; i++)
    {
        char buf[64];
        sprintf(buf, "%s-%d", name, i + 1);

        ThreadDate* td = new ThreadDate(buf, bq);
        threads.emplace_back(func, *td, buf);
        threads.back().Start();
    }
}

void producterStart(std::vector<mythread<ThreadDate>> &threads, block_queue_t &bq)
{
    createThread(product, threads, PRODUCTER_NUM, bq, "producter");
}

void consumerStart(std::vector<mythread<ThreadDate>> &threads, block_queue_t &bq)
{
    createThread(consum, threads, CONSUMER_NUM, bq, "consumer");
}

void wait(std::vector<mythread<ThreadDate>> &threads)
{
    for (auto &thread : threads)
        thread.Join();
}

int main()
{
    std::vector<mythread<ThreadDate>> threads;
    threads.reserve(PRODUCTER_NUM + CONSUMER_NUM);  //预先开辟一段空间
    block_queue_t bq(5);

    producterStart(threads, bq);
    consumerStart(threads, bq);

    wait(threads);
    return 0;
}

// #include <iostream>
// #include <unistd.h>
// #include <pthread.h>
// #include <vector>
// #include <cstdio>

// #define MASTER_NUM 1
// #define SLAVER_NUM 3

// pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
// pthread_cond_t g_cond = PTHREAD_COND_INITIALIZER;

// //master线程通过条件变量控制slaver线程
// void* master(void* arg)
// {
//     while (1)
//     {
//         sleep(2);
//         std::cout << "master 将唤醒一个线程………………" << std::endl;
//         pthread_cond_signal(&g_cond);
//     }

//     return nullptr;
// }
// void* slaver(void* arg)
// {
//     while (1)
//     {
//         pthread_mutex_lock(&g_mutex);
//         pthread_cond_wait(&g_cond, &g_mutex);
//         std::cout << "当前被唤醒的salver线程是：" <<(char*)arg << std::endl;
//         pthread_mutex_unlock(&g_mutex);
//     }

//     return nullptr;
// }

// void masterStart(std::vector<pthread_t>& tids)
// {
//     for (int i = 0; i < MASTER_NUM; i++)
//     {
//         char* buf = new char[64];
//         sprintf(buf, "Master-%d", i + 1);

//         pthread_t tid;
//         pthread_create(&tid, nullptr, master, buf);
//     }
// }

// void slaverStart(std::vector<pthread_t>& tids)
// {
//     for (int i = 0; i < SLAVER_NUM; i++)
//     {
//         char* buf = new char[64];
//         sprintf(buf, "Slaver-%d", i + 1);

//         pthread_t tid;
//         pthread_create(&tid, nullptr, slaver, buf);
//     }
// }

// void wait(std::vector<pthread_t>& tids)
// {
//     for (auto& tid: tids)
//     {
//         pthread_join(tid, nullptr);
//     }
// }

// int main()
// {
//     std::vector<pthread_t> tids;

//     masterStart(tids);
//     slaverStart(tids);

//     while(1);

//     wait(tids);

//     return 0;
// }